package rest

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"
	"launchpad.net/mgo/bson"
	"log"
	"math/rand"
	"net/http"
	"time"
)

type BucketItem bson.M
type Bucket map[string]BucketItem

func NewBucket() Bucket {
	return make(Bucket)
}

func (b Bucket) CopyFrom(urlstr string) error {

	resp, err := http.Get(urlstr)

	if err != nil {
		return err
	}

	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return errors.New("bucket not found at " + urlstr)
	}

	text, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		return err
	}

	log.Println(string(text))

	err = json.Unmarshal(text, &b)

	if err != nil {
		return err
	}

	return nil
}

func (b Bucket) Get(id string) (io.Reader, int, error) {

	item, ok := b[id]

	if !ok {
		return nil, 404, errors.New("resource not found")
	}

	text, err := json.Marshal(item)

	if err != nil {
		return nil, 500, err
	}

	return bytes.NewBuffer(text), 200, nil
}

func (b Bucket) Post(body io.Reader) (string, int, error) {

	id := string(time.Now().String()) + string(rand.Int())

	data, err := ioutil.ReadAll(body)

	if err != nil {
		return id, 500, errors.New("couldn't read POST data")
	}

	var item BucketItem

	err = json.Unmarshal(data, &item)

	if err != nil {
		return id, 400, err
	}

	b[id] = item

	return id, 201, nil
}

func (b Bucket) Put(id string, body io.Reader) (int, error) {

	data, err := ioutil.ReadAll(body)

	if err != nil {
		return 500, errors.New("couldn't read POST data")
	}

	var item BucketItem

	err = json.Unmarshal(data, &item)

	if err != nil {
		return 400, err
	}

	_, exists := b[id]

	b[id] = item

	if !exists {
		return 201, nil
	}

	return 200, nil
}

func (b Bucket) Delete(id string) (int, error) {

	delete(b, id)

	return 200, nil
}

func (b Bucket) List() (io.Reader, int, error) {

	text, err := json.Marshal(b)

	if err != nil {
		return nil, 500, err
	}

	return bytes.NewBuffer(text), 200, nil
}
